﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Collections.Concurrent;
using System.Net;


namespace DotNet.Helper
{
    /// <summary>
    /// Http请求帮助类
    /// </summary>
    public class HttpClentHelper
    {
        private static readonly ConcurrentDictionary<string, XClient> _dic = new ConcurrentDictionary<string, XClient>();
        /// <summary>
        /// 静态构造函数
        /// </summary>
        static HttpClentHelper()
        {
            //允许最大并发链接数
            ServicePointManager.DefaultConnectionLimit = 512;

            _dic.TryAdd("", CreateXClient());
        }

        #region 私有方法
        /// <summary>
        /// 创建XClient
        /// </summary>
        /// <returns></returns>
        private static XClient CreateXClient()
        {
            HttpClientHandler handler = new HttpClientHandler()
            {
                //请求内容缓冲区大小
                MaxRequestContentBufferSize = 100000,
                //使用GZip压缩解压
                AutomaticDecompression = DecompressionMethods.GZip,
                //是否使用代理
                UseProxy = false,
                //代理设置为空
                Proxy = null,
            };

            HttpClient client = new HttpClient(handler);
            //通知服务保持长链接
            //client.DefaultRequestHeaders.Add("Connection", "keep-alive");

            XClient xClient = new XClient();
            xClient.Handler = handler;
            xClient.Client = client;

            return xClient;
        }
        #endregion

        /// <summary>
        /// 根据关键字，创建对应的HttpClient
        /// </summary>
        /// <param name="key"></param>
        public static void CreateHttpClient(string key)
        {
            if (!_dic.TryGetValue(key, out XClient xClient))
            {
                _dic.TryAdd(key, CreateXClient());
            }
        }

        /// <summary>
        /// 设置代理
        /// </summary>
        /// <param name="proxy">代理</param>
        /// <param name="key">HttpClient键</param>
        public static void SetProxy(WebProxy proxy, string key = "")
        {
            if (_dic.TryGetValue(key, out XClient xClient))
            {
                xClient.Handler.UseProxy = true;
                xClient.Handler.Proxy = proxy;
            }
            else
            {
                throw new ArgumentOutOfRangeException("key参数出错", key + "找不到对应的xClient");
            }
        }

        /// <summary>
        /// 添加全局Header
        /// </summary>
        /// <param name="headerKey">Header键</param>
        /// <param name="headerValue">Header值</param>
        /// <param name="key">HttpClient键</param>
        public static void SetHeader(string headerKey, string headerValue, string key = "")
        {
            if (_dic.TryGetValue(key, out XClient xClient))
            {
                xClient.Client.DefaultRequestHeaders.Add(headerKey, headerValue);
            }
            else
            {
                throw new ArgumentOutOfRangeException("key参数出错", key + "找不到对应的xClient");
            }
        }

        /// <summary>
        /// 通过GET请求获取内容
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="key">HttpClient键</param>
        /// <returns></returns>
        public static async Task<XResponse> Get(string url, string key = "")
        {
            XResponse result = new XResponse();
            if (_dic.TryGetValue(key, out XClient xClient))
            {
                var resp = await xClient.Client.GetAsync(url);
                if (!resp.IsSuccessStatusCode)
                {
                    result.StatusCode = (int)resp.StatusCode;
                }
                result.Content = await resp.Content.ReadAsStringAsync();
            }
            else
            {
                throw new ArgumentOutOfRangeException("key参数出错", key + "找不到对应的xClient");
            }
            return result;
        }

        /// <summary>
        /// 通过POST请求获取内容
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="content">请求内容</param>
        /// <param name="key">HttpClient键</param>
        /// <returns></returns>
        public static async Task<XResponse> Post(string url, string content, string key = "")
        {
            XResponse result = new XResponse();
            if (_dic.TryGetValue(key, out XClient xClient))
            {
                StringContent ctx = new StringContent(content);
                var resp = await xClient.Client.PostAsync(url, ctx);
                if (!resp.IsSuccessStatusCode)
                {
                    result.StatusCode = (int)resp.StatusCode;
                }
                result.Content = await resp.Content.ReadAsStringAsync();
            }
            else
            {
                throw new ArgumentOutOfRangeException("key参数出错", key + "找不到对应的xClient");
            }
            return result;
        }

        /// <summary>
        /// 发送http请求
        /// </summary>
        /// <param name="reqMessage">请求实体</param>
        /// <param name="key">HttpClient键</param>
        /// <returns></returns>
        public static async Task<XResponse> Send(HttpRequestMessage reqMessage, string key = "")
        {
            XResponse result = new XResponse();
            if (_dic.TryGetValue(key, out XClient xClient))
            {
                var resp = await xClient.Client.SendAsync(reqMessage);
                if (!resp.IsSuccessStatusCode)
                {
                    result.StatusCode = (int)resp.StatusCode;
                }
                result.Content = await resp.Content.ReadAsStringAsync();
            }
            else
            {
                throw new ArgumentOutOfRangeException("key参数出错", key + "找不到对应的xClient");
            }
            return result;
        }

    }

    /// <summary>
    /// 请求客户端
    /// </summary>
    internal class XClient
    {
        /// <summary>
        /// 请求的默认设置
        /// </summary>
        public HttpClientHandler Handler { get; set; }
        /// <summary>
        /// HttpClient
        /// </summary>
        public HttpClient Client { get; set; }

    }
    /// <summary>
    /// 返回实体
    /// </summary>
    public class XResponse
    {
        /// <summary>
        /// 状态码
        /// </summary>
        public int StatusCode { get; set; } = 200;
        /// <summary>
        /// 回应内容
        /// </summary>
        public string Content { get; set; }
    }

}
